<?php

namespace scaffold\exception;

use exception;
use scaffold\response\Json;
use think\exception\Handle;
use think\facade\Config;
use think\facade\Log;

/**
 * 捕捉异常处理类
 * @author edward <edward@localhost.com>
 */
class ExceptRestructure extends Handle
{
    /**
     * 另外需要捕捉得异常
     * @var array
     */
    protected $report = array(
        '\\scaffold\\exception\\BaseException' => array(
            'name'      => 'BaseException',
            'recode'    => 10099,
            'write_log' => true,
        ),
    );

    /**
     * 默认异常错误码
     * @var integer
     */
    protected $recode = 0;

    /**
     * 写入日志
     * @var boolean
     */
    protected $writeLog = false;

    /**
     * 加载配置
     * @author edward edward@localhost.com
     * @DateTime 2020-08-03
     * @version  1.0.0.0
     *
     */
    public function __construct()
    {
        Config::get('exception.report') && array_merge($this->report, Config::get('exception.report'));
    }

    /**
     * 异常处理
     * @author edward edward@localhost.com
     * @DateTime 2020-08-13
     * @version  1.0.0.0
     *
     * @param    exception  $exception 异常错误
     */
    public function render(exception $exception)
    {
        // 调试模式
        if (Config::get('app_debug')) {
            return parent::render($exception);
        }
        if ($report = $this->isReport($exception)) {
            $this->recode   = $exception->getRecode() ?: $report['recode'];
            $this->writeLog = $exception->getWriteLog() ?: $report['write_log'];
            $this->msg      = $exception->getMessage() ?: $report['name'];
        } else {
            $this->recode   = 10099;
            $this->writeLog = true;
            $this->msg      = 'Sorry,I can not give you what you want.';
        }
        $this->writeLog && $this->log($exception);
        return (new Json)->code($exception->getCode())->recode($this->recode)->msg($this->msg);
    }

    /**
     * 写入日志
     * @author edward edward@localhost.com
     * @DateTime 2020-08-13
     * @version  1.0.0.0
     *
     * @param    exception  $exception 错误
     */
    private function log(exception $exception)
    {
        $data = array(
            'code'    => $exception->getCode(),
            'message' => $exception->getMessage(),
            'file'    => $exception->getFile(),
            'line'    => $exception->getLine(),
        );
        $log = "[{$data['code']}]{$data['message']}[{$data['file']}:{$data['line']}]";
        Log::record($log, 'error');
    }

    /**
     * 是否在需要捕捉异常列表中
     * @author edward edward@localhost.com
     * @DateTime 2020-07-17
     * @version  1.0.0.0
     *
     * @param    exception  $e 异常对象
     * @return   boolean
     */
    private function isReport(exception $e)
    {
        foreach ($this->report as $class => $value) {
            if ($e instanceof $class) {
                return $value;
            }
        }
        return false;
    }
}
